#include "newspaper.h"

NewspaperSegmentation::NewspaperSegmentation(){
	setWindowIcon(QIcon(QPixmap ( QString("images/icon.jpg") )));
	imageLabel = new QLabel(this);
	imageLabel->setBackgroundRole(QPalette::Base);
	imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
	imageLabel->setScaledContents(true);

	scrollArea = new QScrollArea(this);
	scrollArea->setBackgroundRole(QPalette::Dark);
	scrollArea->setWidget(imageLabel);
	setCentralWidget(scrollArea);

	createActions();
	createMenus();
	createToolBars();
	
	for( int i = 0; i < 6; ++i ){
		image_step[i] = 0;
		histogram[i] = 0;
	}
	histogram_image = 0;
	
	setWindowTitle(tr("Newspaper Segmentation"));
	resize(800, 600);
	showMaximized();
	
}

NewspaperSegmentation::~NewspaperSegmentation(){
	for( int i = 0; i < 6; ++i ){
		delete image_step[i];
		delete histogram[i];
	}
	delete histogram_image;
}

void NewspaperSegmentation::open(){
	QString fileName = QFileDialog::getOpenFileName( this, tr("Open File"), QDir::currentPath() + "/input", 
		tr("Image files (*.gif *.jpg *.jpeg *.png);;All files (*.*)"), 0 );
	if (!fileName.isEmpty()) {
		
		deleteImages();
		
		image_step[0] = new QImage(fileName);
		image_step[1] = new QImage(*image_step[0]);
		
		if (image_step[0]->isNull()){
			QMessageBox::information(this, tr("Image Segmentation"),
				tr("Cannot load %1.").arg(fileName));
			return;
		}
		
		setCurrentImage( 0 );
		scaleFactor = 1.0;

		printAct->setEnabled(true);
		fitToWindowAct->setEnabled(true);
		updateActions();

		if (!fitToWindowAct->isChecked())
			imageLabel->adjustSize();
		
		step0Act->setEnabled(true);
		step2Act->setEnabled(true);
		step3Act->setEnabled(true);
		step4Act->setEnabled(true);
		step5Act->setEnabled(true);
		showHistogramAct->setEnabled(true);
	}
}

void NewspaperSegmentation::print(){
	Q_ASSERT(imageLabel->pixmap());
#ifndef QT_NO_PRINTER
	QPrintDialog dialog(&printer, this);
	if (dialog.exec()) {
		QPainter painter(&printer);
		QRect rect = painter.viewport();
		QSize size = imageLabel->pixmap()->size();
		size.scale(rect.size(), Qt::KeepAspectRatio);
		painter.setViewport(rect.x(), rect.y(), size.width(), size.height());
		painter.setWindow(imageLabel->pixmap()->rect());
		painter.drawPixmap(0, 0, *imageLabel->pixmap());
	}
#endif
}

void NewspaperSegmentation::zoomIn(){
	scaleImage(1.25);
}

void NewspaperSegmentation::zoomOut(){
	scaleImage(0.8);
}

void NewspaperSegmentation::normalSize(){
	imageLabel->adjustSize();
	scaleFactor = 1.0;
}

void NewspaperSegmentation::fitToWindow(){
	bool fitToWindow = fitToWindowAct->isChecked();
	scrollArea->setWidgetResizable(fitToWindow);
	if (!fitToWindow){
		normalSize();
	}
	updateActions();
}

void NewspaperSegmentation::about(){
	QMessageBox::about(this, tr("About Newspaper Segmentation"),
		tr("<p>The <b>Newspaper Segmentation</b> is based on <i> Text/Image"
		"separation in document images based on statistical analysis of"
		"texture and Morphological operations</i> paper, and "
		"was developed by Igor and Otavio."
		".</p>"));
}

void NewspaperSegmentation::createActions(){
	
	//MENU FILE
	openAct = new QAction(tr("&Open..."), this);
	openAct->setShortcut(tr("Ctrl+O"));
	connect(openAct, SIGNAL(triggered()), this, SLOT(open()));

	printAct = new QAction(tr("&Print..."), this);
	printAct->setShortcut(tr("Ctrl+P"));
	printAct->setEnabled(false);
	connect(printAct, SIGNAL(triggered()), this, SLOT(print()));

	exitAct = new QAction(tr("E&xit"), this);
	exitAct->setShortcut(tr("Ctrl+Q"));
	connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));

	//MENU VIEW
	zoomInAct = new QAction(QIcon(":/images/zoom_in.jpg"), tr("Zoom &In (25%)"), this);
	zoomInAct->setShortcut(tr("Ctrl++"));
	zoomInAct->setEnabled(false);
	connect(zoomInAct, SIGNAL(triggered()), this, SLOT(zoomIn()));

	zoomOutAct = new QAction(QIcon(":/images/zoom_out.jpg"), tr("Zoom &Out (25%)"), this);
	zoomOutAct->setShortcut(tr("Ctrl+-"));
	zoomOutAct->setEnabled(false);
	connect(zoomOutAct, SIGNAL(triggered()), this, SLOT(zoomOut()));

	normalSizeAct = new QAction(tr("&Normal Size"), this);
	normalSizeAct->setShortcut(tr("Ctrl+S"));
	normalSizeAct->setEnabled(false);
	connect(normalSizeAct, SIGNAL(triggered()), this, SLOT(normalSize()));

	fitToWindowAct = new QAction(tr("&Fit to Window"), this);
	fitToWindowAct->setEnabled(false);
	fitToWindowAct->setCheckable(true);
	fitToWindowAct->setShortcut(tr("Ctrl+F"));
	connect(fitToWindowAct, SIGNAL(triggered()), this, SLOT(fitToWindow()));
	
	//MENU OPERATIONS
	step0Act = new QAction(QIcon(":/images/step0.png"), tr("&Original Image"), this);
	step0Act->setShortcut(tr("Ctrl+0"));
	step0Act->setEnabled(false);
     connect(step0Act, SIGNAL(triggered()), this, SLOT(computeStep0Image()));
	
	step1Act = new QAction(QIcon(":/images/step1.png"), tr("&Histogram Equalization"), this);
	step1Act->setShortcut(tr("Ctrl+1"));
	step1Act->setEnabled(false);
     connect(step1Act, SIGNAL(triggered()), this, SLOT(computeStep1Image()));
	
	step2Act = new QAction(QIcon(":/images/step2.png"), tr("&Energy Image"), this);
	step2Act->setShortcut(tr("Ctrl+2"));
	step2Act->setEnabled(false);
     connect(step2Act, SIGNAL(triggered()), this, SLOT(computeStep2Image()));
	
	step3Act = new QAction(QIcon(":/images/step3.png"), tr("&Binarization by Otsu"), this);
	step3Act->setShortcut(tr("Ctrl+3"));
	step3Act->setEnabled(false);
     connect(step3Act, SIGNAL(triggered()), this, SLOT(computeStep3Image()));
	
	step4Act = new QAction(QIcon(":/images/step4.png"), tr("&Morphological Operations"), this);
	step4Act->setShortcut(tr("Ctrl+4"));
	step4Act->setEnabled(false);
     connect(step4Act, SIGNAL(triggered()), this, SLOT(computeStep4Image()));
	
	step5Act = new QAction(QIcon(":/images/step5.png"), tr("&Final Result"), this);
	step5Act->setShortcut(tr("Ctrl+5"));
	step5Act->setEnabled(false);
     connect(step5Act, SIGNAL(triggered()), this, SLOT(computeStep5Image()));
	
	enableDisableHistogramEqualizationAct = new QAction(QIcon(":/images/eh.gif"), tr("&Enable/Disable Histogram Equalization"), this);
	enableDisableHistogramEqualizationAct->setShortcut(tr("Ctrl+E"));
	enableDisableHistogramEqualizationAct->setCheckable(true);
     connect(enableDisableHistogramEqualizationAct, SIGNAL(toggled(bool)), this, SLOT(enableDisableHistogramEqualization(bool)));
	
	showHistogramAct = new QAction(QIcon(":/images/histogram.jpg"), tr("&Show Histogram"), this);
	showHistogramAct->setShortcut(tr("Ctrl+H"));
	showHistogramAct->setEnabled(false);
     connect(showHistogramAct, SIGNAL(triggered()), this, SLOT(showHistogram()));
	
	//MENU ABOUT
	aboutAct = new QAction(tr("&About"), this);
	connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));

	aboutQtAct = new QAction(tr("About &Qt"), this);
	connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
}

void NewspaperSegmentation::createMenus(){
	fileMenu = new QMenu(tr("&File"), this);
	fileMenu->addAction(openAct);
	fileMenu->addAction(printAct);
	fileMenu->addSeparator();
	fileMenu->addAction(exitAct);

	viewMenu = new QMenu(tr("&View"), this);
	viewMenu->addAction(zoomInAct);
	viewMenu->addAction(zoomOutAct);
	viewMenu->addAction(normalSizeAct);
	viewMenu->addSeparator();
	viewMenu->addAction(fitToWindowAct);

	operationsMenu = new QMenu(tr("&Operations"), this);
	operationsMenu->addAction(step0Act);
	operationsMenu->addAction(step1Act);
	operationsMenu->addAction(step2Act);
	operationsMenu->addAction(step3Act);
	operationsMenu->addAction(step4Act);
	operationsMenu->addAction(step5Act);
	operationsMenu->addSeparator();
	operationsMenu->addAction(enableDisableHistogramEqualizationAct);
	operationsMenu->addAction(showHistogramAct);
	
	helpMenu = new QMenu(tr("&Help"), this);
	helpMenu->addAction(aboutAct);
	helpMenu->addAction(aboutQtAct);

	menuBar()->addMenu(fileMenu);
	menuBar()->addMenu(viewMenu);
	menuBar()->addMenu(operationsMenu);
	menuBar()->addMenu(helpMenu);
}

void NewspaperSegmentation::createToolBars(){
	operationsToolBar = addToolBar(tr("Segmentation steps"));
	operationsToolBar->addAction(step0Act);
	operationsToolBar->addAction(step1Act);
	operationsToolBar->addAction(step2Act);
	operationsToolBar->addAction(step3Act);
	operationsToolBar->addAction(step4Act);
	operationsToolBar->addAction(step5Act);
	operationsToolBar->addSeparator();
	operationsToolBar->addAction(enableDisableHistogramEqualizationAct);
	operationsToolBar->addAction(showHistogramAct);
	
	viewToolBar = addToolBar(tr("View options"));
	viewToolBar->addAction(zoomInAct);
	viewToolBar->addAction(zoomOutAct);
}


void NewspaperSegmentation::updateActions(){
	zoomInAct->setEnabled(!fitToWindowAct->isChecked());
	zoomOutAct->setEnabled(!fitToWindowAct->isChecked());
	normalSizeAct->setEnabled(!fitToWindowAct->isChecked());
}

void NewspaperSegmentation::scaleImage(double factor){
	Q_ASSERT(imageLabel->pixmap());
	scaleFactor *= factor;
	imageLabel->resize(scaleFactor * imageLabel->pixmap()->size());

	adjustScrollBar(scrollArea->horizontalScrollBar(), factor);
	adjustScrollBar(scrollArea->verticalScrollBar(), factor);

	zoomInAct->setEnabled(scaleFactor < 3.0);
	zoomOutAct->setEnabled(scaleFactor > 0.333);
}

void NewspaperSegmentation::adjustScrollBar(QScrollBar *scrollBar, double factor){
	scrollBar->setValue(int(factor * scrollBar->value()
		+ ((factor - 1) * scrollBar->pageStep()/2)));
}

void NewspaperSegmentation::deleteImages(){
	for( int i = 0; i < 6; ++i ){
		delete image_step[i];
		delete histogram[i];
		image_step[i] = 0;
		histogram[i] = 0;
	}
	delete histogram_image;
	histogram_image = 0;
}

void NewspaperSegmentation::setCurrentImage( int k ){
	current_image = k;
	imageLabel->setPixmap(QPixmap::fromImage(*image_step[current_image]));
}

void NewspaperSegmentation::computeStep0Image(){
	setCurrentImage( 0 );
}

void NewspaperSegmentation::showHistogram(){
	delete histogram_image;
	
	if( histogram[current_image] ){
		histogram_image = new Histogram( *histogram[current_image] );
		return;
	}
	
	histogram[current_image] = new vector<float>(256,0);
	
	for( int y = 0; y < image_step[current_image]->height(); ++y ){
		for( int x = 0; x < image_step[current_image]->width(); ++x ){
			int k = qRed(image_step[current_image]->pixel( x, y ));
			(*histogram[current_image])[k] += 1;
		}
	}
	
	histogram_image = new Histogram( *histogram[current_image] );
}

int NewspaperSegmentation::getPixel( QImage* img, int x, int y ){
	if( x >= 0 && x < img->width() && y >= 0 && y < img->height() )
		return qRed( img->pixel( x, y ) );
	else
		return -1;
}

void NewspaperSegmentation::enableDisableHistogramEqualization( bool b ){
	
	step1Act->setEnabled( b );
	
	for( int i = 1; i < 6; ++i ){
		delete image_step[i];
		delete histogram[i];
		image_step[i] = 0;
		histogram[i] = 0;
	}
	delete histogram_image;
	histogram_image = 0;
	
	setCurrentImage( 0 );
	
	if( !b )
		image_step[1] = new QImage(*image_step[0]);
}

#include "step1.cpp"
#include "step2.cpp"
#include "step3.cpp"
#include "step4.cpp"
#include "step5.cpp"

